import { Scene } from '@babylonjs/core/scene';
import { WebXRSessionManager } from '@babylonjs/core/XR/webXRSessionManager';
import { WebXRDefaultExperienceOptions } from '@babylonjs/core/XR/webXRDefaultExperience';
import { VRMotionTeleportation, IVRMotionTeleportationOptions } from './vr-motion/vr-motion-teleportation';
import { IVRMotionMovementOptions, VRMotionMovement } from './vr-motion/vr-motion-movement';
import { IVRMotionLocomotionOptions, VRMotionLocomotion } from './vr-motion/vr-motion-locomotion';
import '@babylonjs/core/Materials/Node/Blocks';
import { IActiveDefaultXRExperienceOptions, IXRContainer, XRContainer } from './xr-container';
import { IXRInputOptions } from './xr-input/xr-input';


/**
 * xr-vr参数对象 
 * @param inputOptions xr输入参数对象 
 * @param disableTeleportation 禁用传送移动 
 * @param teleportationOptions 传送移动参数对象 
 * @param enableMovement 启用控制器移动 
 * @param movementOptions 控制器移动参数对象 
 * @param enableLocomotion 启用原地动作移动 
 * @param locomotionOptions 原地动作移动参数对象 
 */
interface IActiveDefaultVRExperienceOptions extends IActiveDefaultXRExperienceOptions {
    inputOptions?: IXRInputOptions,
    disableTeleportation?: boolean,
    teleportationOptions?: IVRMotionTeleportationOptions,
    enableMovement?: boolean,
    movementOptions?: IVRMotionMovementOptions,
    enableLocomotion?: boolean,
    locomotionOptions?: IVRMotionLocomotionOptions,
}

/**
 * 启用xr，生成vr容器实例
 * @param scene 所在场景
 * @param canvas 画布元素
 * @param options 参数对象
 * @returns vr容器promise对象
 */
const ActiveDefaultVRExperience = async (scene: Scene, canvas: HTMLCanvasElement, options?: IActiveDefaultVRExperienceOptions): Promise<VRContainer | null> => {
    const ops = options || {};
    const vr = new VRContainer();
    await vr.ActiveDefaultXRExperience(scene, canvas, ops);
    return vr;
};

/**
 * vr容器接口
 * @param teleportation vr传送移动
 * @param movement vr控制器移动
 * @param locomotion vr原地动作移动
 */
interface IVRContainer extends IXRContainer<VRContainer> {
    teleportation: VRMotionTeleportation,
    movement: VRMotionMovement,
    locomotion: VRMotionLocomotion,
}


/**
 * vr容器
 */
class VRContainer extends XRContainer<VRContainer> implements IVRContainer {

    public locomotion!: VRMotionLocomotion;
    public movement!: VRMotionMovement;
    public teleportation!: VRMotionTeleportation;

    protected getXROptions(option: IActiveDefaultVRExperienceOptions): WebXRDefaultExperienceOptions {
        const ops = super.getXROptions(option);
        ops.disableTeleportation = option.disableTeleportation;
        ops.inputOptions = {
            doNotLoadControllerMeshes: false,
            customControllersRepositoryURL: option.customControllersRepositoryURL,
        };
        return ops;
    }

    protected setLocomotion(scene: Scene, options: IActiveDefaultVRExperienceOptions): void {
        if (!options.disableTeleportation) return;
        if (options.enableMovement) return;
        if (!options.enableLocomotion) return;
        this.locomotion = new VRMotionLocomotion(this.experience, scene, options.locomotionOptions);
    }

    protected setMovement(scene: Scene, options: IActiveDefaultVRExperienceOptions): void {
        if (!options.disableTeleportation) return;
        if (!options.enableMovement) return;
        this.movement = new VRMotionMovement(this.experience, scene, options.movementOptions);
    }

    protected setTeleportation(scene: Scene, options: IActiveDefaultVRExperienceOptions): void {
        if (options.disableTeleportation) return;
        this.teleportation = new VRMotionTeleportation(this.experience, scene, options.teleportationOptions);
    }

    protected async supportImmersiveMode(): Promise<boolean> {
        return await WebXRSessionManager.IsSessionSupportedAsync('immersive-vr');
    }

}


export { ActiveDefaultVRExperience, VRContainer };
export type { IActiveDefaultVRExperienceOptions, IVRContainer };